package edu.amm.neur;

import java.util.Arrays;

/**
 * Биполярный вектор.
 * 
 * @author Иванов Илья
 * @since 2013-04-28
 */
public class BipolarVector {
	
	private byte[] vector;
	
	/**
	 * Строит биполярный вектор заданной длины, все компоненты которого равны -1.
	 */
	public BipolarVector(int n) {
		if (n <= 0)
			throw new RuntimeException("Некорректная длина вектора");
		
		vector = new byte[n];
		for (int i = 0; i < vector.length; i++)
			vector[i] = -1;
	}
	
	/**
	 * Строит биполярный вектор на основании булевского:
	 * ложному значению ставится в соответствие -1,
	 * истинному значению ставится в соответствие 1.
	 * @param booleanVector Булевский вектор.
	 */
	public BipolarVector(boolean[] booleanVector) {
		if (booleanVector == null)
			throw new RuntimeException("Не задан булевский вектор");
		
		vector = new byte[booleanVector.length];
		for (int i = 0; i < vector.length; i++)
			vector[i] = (byte) (booleanVector[i] ? 1 : -1);
	}
	
	/**
	 * Строит биполярный вектор, копируя переданный.
	 * @param bipolarVector Биполярный вектор для копирования.
	 */
	public BipolarVector(BipolarVector bipolarVector) {
		if (bipolarVector == null)
			throw new RuntimeException("Не задан вектор для копирования");
		
		vector = Arrays.copyOf(bipolarVector.vector, bipolarVector.length());
	}
	
	/**
	 * Копирует в текущий вектор значение переданного вектора.
	 * @param bipolarVector Вектор для копирования.
	 */
	public void copyFrom(BipolarVector bipolarVector) {
		if (bipolarVector == null || length() != bipolarVector.length())
			throw new RuntimeException("Некорректный вектор для копирования");
		
		vector = Arrays.copyOf(bipolarVector.vector, bipolarVector.length());
	}
	
	/**
	 * @return Длина вектора.
	 */
	public int length() {
		return vector.length;
	}
	
	/**
	 * @param i Индекс элемента.
	 * @param value Значение элемента.
	 */
	public void set(int i, byte value) {
		if (value != -1 && value != 1)
			throw new RuntimeException("Некорректное биполярное значение");
		
		vector[i] = value;
	}
	
	/**
	 * @param i Индекс элемента, отсчитывая от 0.
	 * @return i-й элемент вектора.
	 */
	public byte get(int i) {
		return vector[i];
	}
	
	/**
	 * Булевское представление биполярного вектора:
	 * каждому элементу -1 ставится в соответствие ложное значение,
	 * каждому элементу 1 ставится в соответствие истинное значение.
	 * @return Булевское представление биполярного вектора.
	 */
	public boolean[] asBooleanVector() {
		boolean[] bools = new boolean[length()];
		for (int i = 0; i < bools.length; i++)
			bools[i] = get(i) == -1 ? false : true;
		
		return bools;
	}
	
	/**
	 * Проверяет на равенство другому вектору.
	 * @param another Другой вектор.
	 * @return <code>true</code>, если выполняется поэлементное равенство.
	 */
	public boolean equals(BipolarVector another) {
		if (this == another)
			return true;
		if (another == null || length() != another.length())
			return false;
		
		int length = length();
		for (int i = 0; i < length; i++)
			if (get(i) != another.get(i))
				return false;
				
		return true;
	}
}